package de.blitzcoder.collide.gui;

import de.blitzcoder.collide.util.Log;
import java.io.File;
import java.util.LinkedList;
import java.util.ListIterator;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;

/**
 *
 * This abstract class represents a DocumentManager in CollIDE
 *
 * @author blitzcoder
 */
public abstract class DocumentManager {

    public DocumentManager() {
        super();
    }

    public abstract void bringToFront(Document doc);

    public void nextDocument() {
        int count = getDocumentCount();
        int index = getCurrentDocumentIndex();

        Log.log("Current: "+index);

        if (count == 0)
            return;
        if (index < count-1) {
            index++;
        } else if (index == count-1) {
            index = 0;
        } else {
            index = 0;
        }

        Log.log("Selecting "+index);

        bringToFront(getDocumentAtIndex(index));
    }

    public void previousDocument() {
        int count = getDocumentCount();
        int index = getCurrentDocumentIndex();

        if (count == 0)
            return;

        if (index < 1) {
            index = count -1;
        } else {
            index--;
        }

        bringToFront(getDocumentAtIndex(index));
    }

    public abstract boolean removeDocument(Document doc);

    public abstract Document getCurrentDocument();
    public abstract int getCurrentDocumentIndex();
    public abstract Document[] getAllDocuments();

    public abstract void finishDocumentInsertion(Document doc);
    public abstract void startDocumentInsertion(Document doc);

    public abstract JComponent getComponent();


    private LinkedList<DocumentManagerListener> documentListeners = new LinkedList<DocumentManagerListener>();
    public void addDocumentManagerListener(DocumentManagerListener l) {
        documentListeners.addLast(l);
    }
    public void removeDocumentManagerListener(DocumentManagerListener l) {
        documentListeners.remove(l);
    }
    public void fireDocumentRemoved(Document doc) {
        ListIterator<DocumentManagerListener> it = documentListeners.listIterator();
        while (it.hasNext())
            it.next().documentRemoved(doc);
    }
    public void fireDocumentAdded(Document doc) {
        ListIterator<DocumentManagerListener> it = documentListeners.listIterator();
        while (it.hasNext())
            it.next().documentAdded(doc);
    }
    public void fireDocumentSelected(Document doc) {
        ListIterator<DocumentManagerListener> it = documentListeners.listIterator();
        while (it.hasNext())
            it.next().documentSelected(doc);
    }

    public int getDocumentCount() {
        return getAllDocuments().length;
    }

    public void addDocument(final Document doc) {        
        startDocumentInsertion(doc);
        
        DocumentLoader loader = new DocumentLoader(doc);
        loader.start();
    }

    private Document getDocumentAtIndex(int index) {
        return getAllDocuments()[index];
    }

    public boolean removeAllDocuments() {
        return removeOtherDocuments(null);
    }

    public boolean removeOtherDocuments(Document notToRemove) {
        Document[] docs = getAllDocuments();
        boolean ok = true;
        for (Document doc:docs)
            if (doc != notToRemove)
                if (!removeDocument(doc))
                    ok = false;
        return ok;
    }

    protected int getIndexForDocument(Document doc) {
        Document[] docs = getAllDocuments();
        for (int i=0;i<docs.length;i++)
            if (docs[i] == doc)
                return i;
        return -1;
    }

    public boolean documentAvailable(Document doc) {
        Document[] docs = getAllDocuments();
        for (Document doc_:docs)
            if (doc_ == doc)
                return true;
        return false;
    }

    

    public Document getDocumentForFile(File f) {
        Document[] docs = getAllDocuments();
        for (Document doc:docs)
            if (doc.equalsFile(f))
                return doc;
        return null;
    }

    private class DocumentLoader extends Thread {

        private Document document;

        public DocumentLoader(Document doc) {
            super("DocumentLoader");
            this.document = doc;
        }

        @Override
        public void run() {


            try {

                document.load();

            } catch (Exception ex) {
                ex.printStackTrace();
                removeDocument(document);
                return;

            }

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    finishDocumentInsertion(document);
                    document.afterLoad();
                }
            });

        }
    }
}